#pragma once
#include "Log.hpp"
#include "Util.hpp"
#include "Common.hpp"
#include "Socket.hpp"
#include <sstream>
#include <functional>
#include <unordered_map>
using namespace MyLog;
using namespace MySocket;

const std::string glinesep = ": ";
const std::string glinespace = "\r\n";
const std::string rgsep = " ";

const std::string webroot = "./wwwroot";
const std::string homepage = "index.html";
const std::string page_404 = "/404.html";

class HttpRequest
{
public:
    HttpRequest() : _is_interact(false) {}

    //不需要实现
    bool Serialize()
    {
        return true;
    }

    void ParseReqLine(std::string &reqstr)
    {
        std::stringstream ss(reqstr);
        ss >> _method >> _uri >> _version;
    }

    const std::string URI()
    {
        return _uri;
    }

    //反序列化
    bool DeSerialize(std::string &reqstr)
    {
        std::string reqline;
        bool ret = Util::ReadOneLine(reqstr, &reqline, glinespace);
        LOG(Loglevel::DEBUG) << reqline;

        ParseReqLine(reqline);

        if (URI() == "/")
            _uri = webroot + _uri + homepage;
        else
            _uri = webroot + _uri;

        LOG(Loglevel::DEBUG) << "_method: " << _method;
        LOG(Loglevel::DEBUG) << "_uri: " << _uri;
        LOG(Loglevel::DEBUG) << "_version: " << _version;
        const std::string sep = "?";

        auto pos = _uri.find(sep);
        if (pos == std::string::npos)
        {
            return true;
        }

        _args = _uri.substr(pos + sep.size());
        _uri = _uri.substr(0, pos);
        _is_interact = true;
        return true;
    }

    std::string Args() { return _args; }
    bool IsInteract() { return _is_interact; }
    ~HttpRequest() {}

private:
    std::string _method;
    std::string _uri;
    std::string _version;

    std::unordered_map<std::string, std::string> _reqhead;
    std::string _blank;
    std::string _text;

    std::string _args;
    bool _is_interact;
};

class HttpResponse
{
public:
    HttpResponse() : _blank(glinespace), _version("HTTP/1.0s") {}

    //序列化
    std::string Serialize()
    {
        std::string status_line = _version + rgsep + std::to_string(_code) + rgsep + _desc + glinespace;
        std::string resheads;
        for (auto &head : _reshead)
            resheads += head.first + glinesep + head.second + glinespace;

        Util::ReadFileContent(targetfile, &_rtext);
        return status_line + resheads + _blank + _rtext;
    }

    //设置文件路径
    void SetTargetFile(const std::string &target)
    {
        targetfile = target;
    }

    void SetCode(int code)
    {
        _code = code;
        switch (code)
        {
        case 200:
            _desc = "OK";
            break;
        case 404:
            _desc = "NOT FOUND";
            break;
        case 301:
            _desc = "Moved Permanently";
            break;
        case 302:
            _desc = "SEE OTHER";
            break;
        default:
            break;
        }
    }

    //添加报头
    void SetHeader(const std::string &key, const std::string &val)
    {
        auto iter = _reshead.find(key);
        if (iter == _reshead.end())
            _reshead.insert(std::make_pair(key, val));
    }

    std::string UriSuffix(const std::string &tgfile)
    {
        // ./wwwroot/a/b/c.html
        auto pos = tgfile.rfind(".");
        if (pos == std::string::npos)
        {
            return "text/html";
        }

        std::string suffix = tgfile.substr(pos);
        if (suffix == ".html" || suffix == ".htm")
            return "text/html";
        else if (suffix == ".jpg")
            return "image/jpeg";
        else if (suffix == "png")
            return "image/png";
        else
            return "";
    }

    bool MakeResponse()
    {
        if (targetfile == "./wwwroot/favicon.ico")
        {
            LOG(Loglevel::DEBUG) << "用户请求: " << targetfile << "忽略它";
            return false;
        }
        if (targetfile == "./wwwroot/redir_test")
        {
            SetCode(301);
            SetHeader("Location", "https://www.qq.com/");
            return true;
        }

        int filesize = 0;
        bool ret = Util::ReadFileContent(targetfile, &_rtext);
        if (!ret)
        {
            LOG(Loglevel::WARN) << "client want to get " << targetfile << " not found";
            _rtext = "";
            SetCode(404);
            targetfile = webroot + page_404;
            filesize = Util::FileSize(targetfile);
            Util::ReadFileContent(targetfile, &_rtext);
            std::string suffix = UriSuffix(targetfile);
            SetHeader("Content-Type", suffix);
            SetHeader("Content-length", std::to_string(filesize));
        }
        else
        {
            LOG(Loglevel::DEBUG) << "读取文件->" << targetfile;
            SetCode(200);
            filesize = Util::FileSize(targetfile);
            std::string suffix = UriSuffix(targetfile);
            SetHeader("Content-Type", suffix);
            SetHeader("Content-length", std::to_string(filesize));
        }
        return true;
    }

    void SetText(const std::string &t)
    {
        _rtext = t;
    }

    bool DeSerialize()
    {
        return true;
    }
    ~HttpResponse() {}

private:
    std::string _version;
    int _code;
    std::string _desc;

    std::unordered_map<std::string, std::string> _reshead;
    std::string _blank;
    std::string _rtext;

    std::string targetfile;
};

using http_func_t = std::function<void(HttpRequest &req, HttpResponse &resp)>;


void Login(HttpRequest &req, HttpResponse &resp)
{
    LOG(Loglevel::DEBUG) << req.Args() << ", 我们成功进入到了处理数据的逻辑";
    std::string text = "hello " + req.Args();

    resp.SetCode(200);
    resp.SetHeader("Content-Type", "text/plain");
    resp.SetHeader("Content-Length", std::to_string(text.size()));
    resp.SetText(text);
}

void Register(HttpRequest &req, HttpResponse &resp)
{
    LOG(Loglevel::DEBUG) << req.Args() << ", 我们成功进入到了处理数据的逻辑";
    std::string text = "hello " + req.Args();

    resp.SetCode(200);
    resp.SetHeader("Content-Type", "text/plain");
    resp.SetHeader("Content-Length", std::to_string(text.size()));
    resp.SetText(text);
}

void VipCheck(HttpRequest &req, HttpResponse &resp)
{
    LOG(Loglevel::DEBUG) << req.Args() << ", 我们成功进入到了处理数据的逻辑";
    std::string text = "hello " + req.Args();
    
    resp.SetCode(200);
    resp.SetHeader("Content-Type", "text/plain");
    resp.SetHeader("Content-Length", std::to_string(text.size()));
    resp.SetText(text);
}


class Http
{
public:
    Http()
    {
        RegisterServer("/login",Login);
        RegisterServer("/register",Register);
        RegisterServer("/vip_check",VipCheck);
    }

    //处理请求
    bool HttpHandlerRequest(std::string &httpreqstr, std::string& packag)
    {
        if(httpreqstr.empty())
            return false;
        HttpResponse resp;
        HttpRequest req;

        req.DeSerialize(httpreqstr);
        if (req.IsInteract())
        {
            if (_route.find(req.URI()) == _route.end())
            {
                return false;
            }
            else
            {
                _route[req.URI()](req, resp);
                std::string resp_str = resp.Serialize();
                packag += resp_str;
                return true;
            }
        }
        else
        {
            resp.SetTargetFile(req.URI());
            if (resp.MakeResponse())
            {
                std::string resp_str = resp.Serialize();
                packag += resp_str;
                return true;
            }
        }
        return true;
    }

    void RegisterServer(const std::string &name, http_func_t h)
    {
        std::string key = webroot + name;
        auto iter = _route.find(name);
        if (iter == _route.end())
        {
            _route.insert(std::make_pair(key, h));
        }
    }

    ~Http() {}

private:
    std::unordered_map<std::string, http_func_t> _route;
};
